/***************************************************************************
 *   Copyleft 2008-2009 by												   *
 *	 Iwanicki Krzysztof													   *
 *   <gamma.mini.pw.edu.pl/~iwanickik>									   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 ***************************************************************************/
#include "./vString.h"
#include "../Exceptions/vExceptions.h"

namespace Vendetta {
	vUInt vString::MaxPos = (vUInt) std::string::npos;
	const vString vString::Blank;

	vString::vString() {
	}

	vString::vString(std::string& str) {
		mData = std::string(str);
	}

	vString::vString(const std::string& str) {
		mData = std::string(str);
	}

	vString::vString(const vString& str) {
		mData = std::string(str.mData);
	}

	vString::vString(const vChar* str) {
		mData = std::string(str);
	}

	vString::vString(vChar* str) {
		mData = std::string(str);
	}

	vString::~vString() {
		mData.clear();
	}

	const vChar& vString::operator[](vUInt pos) const {
		try {
			return mData.at(pos);
		} catch (std::exception&) {
			throw vFatalException("Index out of bounds.In const vString::operator[].");
		}
	}

	vChar& vString::operator[](vUInt pos) {
		try {
			return mData.at(pos);
		} catch (std::exception&) {
			throw vFatalException("Index out of bounds.In vString::operator[].");
		}
	}

	const vChar& vString::At(vUInt pos) const {
		try {
			return mData.at(pos);
		} catch (std::exception&) {
			throw vFatalException("Index out of bounds.In vString::At.");
		}
	}
    
	vChar& vString::At(vUInt pos) {
		try {
			return mData.at(pos);
		} catch (std::exception&) {
			throw vFatalException("Index out of bounds.In vString::At.");
		}
	}

	vString vString::ToUpperCase() {
		std::string str = mData;
		std::transform(str.begin(), str.end(), str.begin(), (vInt (*) (vInt)) std::toupper);

		return vString(str);
	}

	vString vString::ToLowerCase() {
		std::string str = mData;
		std::transform(str.begin(), str.end(), str.begin(), (vInt (*) (vInt)) std::tolower);

		return vString(str);
	}

	vString operator+(const vString& str1, const vString& str2) {
		vString retStr;

		retStr.mData = str1.mData + str2.mData;

		return retStr;
	}

	vBool operator==(const vString& lhs, const vString& rhs){
		return (lhs.mData == rhs.mData);
	}
	
	vBool operator==(const vChar* lhs, const vString& rhs) {
		return (lhs == rhs.mData);
	}

	vBool operator==(const vString& lhs, const vChar* rhs) {
		return (lhs.mData == rhs);
	}

	vBool operator!=(const vString& lhs, const vString& rhs) {
		return (lhs.mData != rhs.mData);
	}

	vBool operator!=(const vChar* lhs, const vString& rhs) {
		return (lhs != rhs.mData);
	}

	vBool operator!=(const vString& lhs, const vChar* rhs) {
		return (lhs.mData != rhs);
	}

	vBool operator<(const vString& lhs, const vString& rhs) {
		return (lhs.mData < rhs.mData);
	}

	vBool operator<(const vChar* lhs, const vString& rhs) {
		return (lhs < rhs.mData);
	}

	vBool operator<(const vString& lhs, const vChar* rhs) {
		return (lhs.mData < rhs);
	}

	vBool operator>(const vString& lhs, const vString& rhs) {
		return (lhs.mData > rhs.mData);
	}

	vBool operator>(const vChar* lhs, const vString& rhs) {
		return (lhs > rhs.mData);
	}

	vBool operator>(const vString& lhs, const vChar* rhs) {
		return (lhs.mData > rhs);
	}

	vBool operator<=(const vString& lhs, const vString& rhs) {
		return (lhs.mData <= rhs.mData);
	}

	vBool operator<=(const vChar* lhs, const vString& rhs) {
		return (lhs <= rhs.mData);
	}

	vBool operator<=(const vString& lhs, const vChar* rhs) {
		return (lhs.mData <= rhs);
	}

	vBool operator>=(const vString& lhs, const vString& rhs) {
		return (lhs.mData >= rhs.mData);
	}

	vBool operator>=(const vChar* lhs, const vString& rhs) {
		return (lhs >= rhs.mData);
	}

	vBool operator>=(const vString& lhs, const vChar* rhs) {
		return (lhs.mData >= rhs);
	}

	std::ostream& operator<<(std::ostream& out, const vString& str) {
		out<<str.mData;

		return out;
	}

	std::istream& operator>>(std::istream& in, vString& str) {
		in>>str.mData;

		return in;
	}

	std::istream& GetLine(std::istream& in, vString& str, vChar delim) {
		return std::getline(in, str.mData, delim);
	}

	std::istream& GetLine(std::istream& in, vString& str) {
		return std::getline(in, str.mData);
	}
}
